home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / prefix / import.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-15  |  54.7 KB  |  1,868 lines

  1. /***********************************************************************
  2.  *
  3.  * PROJECT:      PMake
  4.  * MODULE:      Prefix -- Prefix Importation
  5.  * FILE:      import.c
  6.  *
  7.  * AUTHOR:        Adam de Boor: Jul  5, 1989
  8.  *
  9.  * ROUTINES:
  10.  *    Name              Description
  11.  *    ----              -----------
  12.  *    Import_Init         Initialize the module
  13.  *    Import_MountPrefix  Mount a prefix on ourselves
  14.  *    Import_CreatePrefix Create and initialize a Prefix structure
  15.  *                        FOR AN EXISTING DIRECTORY. Not suitable
  16.  *                for prefixes under a root.
  17.  *
  18.  * REVISION HISTORY:
  19.  *    Date      Name        Description
  20.  *    ----      ----        -----------
  21.  *    7/ 5/89      ardeb        Initial version
  22.  *
  23.  * DESCRIPTION:
  24.  *    Functions to deal with importing prefixes.
  25.  *
  26.  *    A prefix appears to the kernel as if it were a read-only,
  27.  *    empty directory until the first LOOKUP operation is performed
  28.  *    on it. The LOOKUP operation is redirected, by claiming the
  29.  *    file in question is a symbolic link, to the MOUNT_DIR (the
  30.  *    exact destination is MOUNT_DIR/<prefix>.<generation>/<component>,
  31.  *    where <prefix> is the ascii representation of the address of the
  32.  *    Prefix structure, <generation> is the ascii representation of the
  33.  *    prefix's generation number, and <component> is the component being
  34.  *    sought).
  35.  *
  36.  *    When the kernel does a LOOKUP operation in MOUNT_DIR, we
  37.  *    unmount the prefix and mount the real one, then redirect the
  38.  *    kernel back there again....
  39.  *
  40.  *    NOTE: ANY fhandle_t RETURNED TO THE KERNEL SHOULD BE ZEROED
  41.  *          OUT BEFORE STORING THE VALUE IN IT, AS THE SUN 
  42.  *          IMPLEMENTATION, AT LEAST, USES BYTES 1, 5 AND 15 FOR
  43.  *          HASHING.
  44.  *
  45.  *     Copyright (c) Berkeley Softworks 1989
  46.  *     Copyright (c) Adam de Boor 1989
  47.  *
  48.  *     Permission to use, copy, modify, and distribute this
  49.  *     software and its documentation for any non-commercial purpose
  50.  *    and without fee is hereby granted, provided that the above copyright
  51.  *     notice appears in all copies.  Neither Berkeley Softworks nor
  52.  *     Adam de Boor makes any representations about the suitability of this
  53.  *     software for any purpose.  It is provided "as is" without
  54.  *     express or implied warranty.
  55.  *
  56.  ***********************************************************************/
  57. #ifndef lint
  58. static char *rcsid =
  59. "$Id: import.c,v 1.16 89/10/10 00:32:09 adam Exp $";
  60. #endif lint
  61.  
  62. #include    "prefix.h"
  63. #include    "rpc.h"
  64. #include    "sunrpc.h"
  65.  
  66. #include    <arpa/inet.h>
  67. #include    <netdb.h>
  68.  
  69. static int      prefixSvc;      /* Socket for prefix NFS requests */
  70.  
  71. /*
  72.  * Token we allocate when given a LOOKUP operation on a prefix. Points
  73.  * to the prefix involved as well as the name of the component that was
  74.  * being looked up before we redirected the kernel to our mount directory.
  75.  *
  76.  * A LookupToken remains valid for 10 seconds after it is created, after
  77.  * which it is deleted from the tokens list. Any later use of a handle with
  78.  * the token's address in it will be rejected.
  79.  *
  80.  * When a token is deleted, it is placed on the freeTokens list to be
  81.  * re-used later. Each token has a "generation number" that is simply
  82.  * a counter that gets incremented each time the token is allocated. The
  83.  * generation number of the token is returned in the fhandle and compared
  84.  * when a readlink is performed to ensure the kernel's idea and our idea
  85.  * of what is being looked up coincide. The generation number is set to
  86.  * zero when the token is first allocated.
  87.  *
  88.  * Maintaining a pool of free tokens allows us to make sure that if the
  89.  * kernel ever comes back with a lookup token, we won't be deceived into
  90.  * doing something bad because the memory has been re-used and happens to
  91.  * contain good values in the fields used for checking token validity.
  92.  */
  93. typedef struct _LookupToken {
  94.     Prefix      *prefix;        /* Prefix in which the name was looked up */
  95.     char        *name;            /* Name that was sought */
  96.     int            generation;     /* Generation number for this token */
  97.     Rpc_Event    nukeEvent;    /* Event that will biff this token. Needed in
  98.                  * case the token must be nuked prematurely,
  99.                  * e.g. when a temporary prefix gets nixed */
  100. } LookupToken;
  101.  
  102. static Lst      tokens;        /* List of active tokens */
  103. static Lst      freeTokens;     /* Pool of previously allocated tokens that
  104.                  * can be reused */
  105.  
  106. #define IS_LOOKUP_HAN(f) (((PrefixHandle *)f)->type == PH_LOOKUP)
  107. #define IS_VALID_LH(f) \
  108.     ((((PrefixHandle *)f)->ld.generation == \
  109.       ((PrefixHandle *)f)->ld.ltp->generation) && \
  110.      (Lst_Member(tokens, (ClientData)((PrefixHandle *)f)->ld.ltp) != NILLNODE))
  111.  
  112. /*
  113.  * Given a buffer and a LookupToken, place the path-via-MOUNT_DIR-for-
  114.  * redirecting-the-kernel-("Look! A UFO!")-while-we-mount-the-real-FS into
  115.  * the buffer.
  116.  */
  117. #define LT_PATH(dest,ltp) sprintf(dest, "%s/%d.%d/%s", MOUNT_DIR, \
  118.                   ((LookupToken *)ltp)->prefix, \
  119.                   ((LookupToken *)ltp)->prefix->generation, \
  120.                   ((LookupToken *)ltp)->name)
  121.  
  122. /*
  123.  * Attributes returned for any symbolic link
  124.  */
  125. struct nfsfattr    link_attr = {
  126.     NFLNK,            /* na_type */
  127.     0777 | S_IFLNK,        /* na_mode */
  128.     1,                /* na_nlink */
  129.     0,                /* na_uid */
  130.     0,                /* na_gid */
  131.     0,                /* na_size (filled in later) */
  132.     0,                /* na_blocksize (filled in later) */
  133.     -1,                /* na_rdev (Garbage) */
  134.     1,                /* na_blocks */
  135.     -1,                /* na_fsid (Garbage) */
  136.     16,                /* na_nodeid (Garbage) */
  137.     {0,0},            /* na_atime (Garbage) */
  138.     {0,0},            /* na_mtime (Garbage) */
  139.     {0,0},            /* na_ctime (Garbage) */
  140. };
  141.  
  142. /* FORWARD DECL */
  143. static int ImportDeleteTemp();
  144. /******************************************************************************
  145.  *
  146.  *               UTILITY ROUTINES
  147.  *
  148.  *****************************************************************************/
  149.  
  150. /***********************************************************************
  151.  *                ImportTokenToHandle
  152.  ***********************************************************************
  153.  * SYNOPSIS:        Convert a LookupToken into an NFS handle
  154.  * CALLED BY:        ImportLookupReq
  155.  * RETURN:        Nothing
  156.  * SIDE EFFECTS:    Handle is filled in.
  157.  *
  158.  * STRATEGY:
  159.  *
  160.  * REVISION HISTORY:
  161.  *    Name    Date        Description
  162.  *    ----    ----        -----------
  163.  *    ardeb    10/ 9/89    Initial Revision
  164.  *
  165.  ***********************************************************************/
  166. static void
  167. ImportTokenToHandle(ltp, fh)
  168.     LookupToken        *ltp;
  169.     fhandle_t        *fh;
  170. {
  171.     PrefixHandle    *lhp;           /* Internal form */
  172.  
  173.     lhp = (PrefixHandle *)fh;
  174.     
  175.     /*
  176.      * Make sure unused bytes are 0
  177.      */
  178.     bzero(fh, sizeof(*fh));
  179.     /*
  180.      * Set up significant fields.
  181.      */
  182.     lhp->ld.type =          PH_LOOKUP;
  183.     lhp->ld.generation =    ltp->generation;
  184.     lhp->ld.ltp =           ltp;
  185. }
  186.  
  187. /***********************************************************************
  188.  *            ImportDeleteLookupToken
  189.  ***********************************************************************
  190.  * SYNOPSIS:        Nuke an expired LookupToken
  191.  * CALLED BY:        Rpc event, ImportDeleteTemp, ImportDelete
  192.  * RETURN:        FALSE (don't stay awake)
  193.  * SIDE EFFECTS:    The token's name is freed and the token itself is
  194.  *                shifted to the freeTokens list with its generation
  195.  *                number increased by one.
  196.  *
  197.  * STRATEGY:
  198.  *
  199.  * REVISION HISTORY:
  200.  *    Name    Date        Description
  201.  *    ----    ----        -----------
  202.  *    ardeb    7/ 5/89        Initial Revision
  203.  *
  204.  ***********************************************************************/
  205. static Boolean
  206. ImportDeleteLookupToken(ltp, ev)
  207.     LookupToken        *ltp;        /* Token to nuke */
  208.     Rpc_Event        ev;         /* Event that called us */
  209. {
  210.     LstNode        ln;
  211.  
  212.     /*
  213.      * Locate and remove the token from the list of valid tokens.
  214.      */
  215.     ln = Lst_Member(tokens, (ClientData)ltp);
  216.     Lst_Remove(tokens, ln);
  217.  
  218.     /*
  219.      * Free its memory.
  220.      */
  221.     free(ltp->name);
  222.  
  223.     /*
  224.      * Put it back in the pool, upping its generation number to make life
  225.      * easier when checking (should very rarely have to do a Lst_Member).
  226.      */
  227.     ltp->generation += 1;
  228.     (void)Lst_AtEnd(freeTokens, (ClientData)ltp);
  229.  
  230.     /*
  231.      * Don't want to be called again...
  232.      */
  233.     Rpc_EventDelete(ev);
  234.  
  235.     /*
  236.      * No need to stay awake on our account.
  237.      */
  238.     return(FALSE);
  239. }
  240.  
  241. /***********************************************************************
  242.  *                ImportAllocLookupToken
  243.  ***********************************************************************
  244.  * SYNOPSIS:        Allocate a new lookup token
  245.  * CALLED BY:        ImportLookupReq
  246.  * RETURN:        A token to use.
  247.  * SIDE EFFECTS:    A token will be removed from the freeTokens list,
  248.  *                if possible.
  249.  *
  250.  * STRATEGY:
  251.  *
  252.  * REVISION HISTORY:
  253.  *    Name    Date        Description
  254.  *    ----    ----        -----------
  255.  *    ardeb    10/ 9/89    Initial Revision
  256.  *
  257.  ***********************************************************************/
  258. static LookupToken *
  259. ImportAllocLookupToken()
  260. {
  261.     LookupToken    *ltp;
  262.  
  263.     if (!Lst_IsEmpty(freeTokens)) {
  264.     ltp = (LookupToken *)Lst_DeQueue(freeTokens);
  265.     } else {
  266.     ltp = (LookupToken *)malloc(sizeof(LookupToken));
  267.     ltp->generation = 0;    /* First-generation */
  268.     }
  269.     return(ltp);
  270. }
  271.  
  272. /***********************************************************************
  273.  *                ImportSetLinkAttr
  274.  ***********************************************************************
  275.  * SYNOPSIS:        Setup returned attributes to be for a link to the
  276.  *                given path.
  277.  * CALLED BY:        ImportLookup, ImportGetAttr
  278.  * RETURN:        Nothing
  279.  * SIDE EFFECTS:
  280.  *
  281.  * STRATEGY:
  282.  *
  283.  * REVISION HISTORY:
  284.  *    Name    Date        Description
  285.  *    ----    ----        -----------
  286.  *    ardeb    7/11/89        Initial Revision
  287.  *
  288.  ***********************************************************************/
  289. static void
  290. ImportSetLinkAttr(attrPtr, path, pp)
  291.     struct nfsfattr *attrPtr;        /* Place to store attributes */
  292.     char            *path;          /* Destination of link */
  293.     Prefix          *pp;            /* Prefix containing the link */
  294. {
  295.     *attrPtr = link_attr;
  296.         
  297.     /*
  298.      * Fill in specific fields that need filling (size,
  299.      * in case kernel uses it for storage when doing the
  300.      * read, and blocksize, for the hell of it).
  301.      */
  302.     attrPtr->na_size        = strlen(path);
  303.     attrPtr->na_blocksize   = pp->attr.na_blocksize;
  304. }
  305. /******************************************************************************
  306.  *
  307.  *               PREFIX LOCATION
  308.  *
  309.  *****************************************************************************/
  310.  
  311. /***********************************************************************
  312.  *                ImportLocateResponse
  313.  ***********************************************************************
  314.  * SYNOPSIS:        Handle response from our PREFIX_LOCATE broadcast
  315.  * CALLED BY:        Rpc
  316.  * RETURN:        1 (stop broadcast)
  317.  * SIDE EFFECTS:    The server, serverName and remote fields of the
  318.  *                'searching' prefix are filled in based on the
  319.  *                response.
  320.  *
  321.  * STRATEGY:
  322.  *      - Figure name of responder
  323.  *    - Write result to console
  324.  *    - Allocate room for and store the server and remote directory
  325.  *    - Record server's address
  326.  *
  327.  * REVISION HISTORY:
  328.  *    Name    Date        Description
  329.  *    ----    ----        -----------
  330.  *    ardeb    7/ 5/89        Initial Revision
  331.  *
  332.  ***********************************************************************/
  333. static Boolean
  334. ImportLocateResponse(from, len, data, searching)
  335.     struct sockaddr_in    *from;        /* Source of response */
  336.     int                    len;        /* Size of return data buffer */
  337.     Rpc_Opaque            data;        /* Data returned */
  338.     Prefix              *searching; /* Prefix for which we're searching */
  339. {
  340.     struct hostent      *he;        /* Description of host to which 'from'
  341.                      * belongs */
  342.     char                *name;        /* Name to use for server */
  343.  
  344.     /*
  345.      * We'd like to put/print the host name, not just its address, so
  346.      * try and convert from an address into a name, leaving the final
  347.      * result pointed to by "name"
  348.      */
  349.     he = gethostbyaddr(&from->sin_addr,
  350.                sizeof(from->sin_addr),
  351.                AF_INET);
  352.  
  353.     if (he) {
  354.     /*
  355.      * Trim off any domain that's there...
  356.      */
  357.     name = (char *)index(he->h_name, '.');
  358.     if (name != NULL) {
  359.         *name = '\0';
  360.     }
  361.     name = he->h_name;
  362.     } else {
  363.     name = InetNtoA(from->sin_addr);
  364.     }
  365.  
  366.     /*
  367.      * Complete "Broadcasting for..." message.
  368.      */
  369.     if (!quiet) {
  370.     Message("served by %s[%s]", name, data);
  371.     }
  372.  
  373.     /*
  374.      * Allocate room for the two strings we need to store
  375.      */
  376.     searching->serverName = (char *)malloc(strlen(name) + 1);
  377.     searching->remote = (char *)malloc(strlen((char *)data) + 1);
  378.  
  379.     /*
  380.      * Store the server data in the prefix entry
  381.      */
  382.     searching->server = *from;
  383.     strcpy(searching->serverName, name);
  384.     strcpy(searching->remote, (char *)data);
  385.  
  386.     /*
  387.      * Stop broadcasting
  388.      */
  389.     return(1);
  390. }
  391.  
  392. /***********************************************************************
  393.  *                ImportLocatePrefix
  394.  ***********************************************************************
  395.  * SYNOPSIS:        Find the server for a prefix.
  396.  * CALLED BY:        ImportReadLink
  397.  * RETURN:        1 if server found.
  398.  * SIDE EFFECTS:    The serverName, remote and server fields of the
  399.  *                prefix are filled in.
  400.  *
  401.  * STRATEGY:
  402.  *
  403.  * REVISION HISTORY:
  404.  *    Name    Date        Description
  405.  *    ----    ----        -----------
  406.  *    ardeb    7/11/89        Initial Revision
  407.  *
  408.  ***********************************************************************/
  409. static int
  410. ImportLocatePrefix(pp)
  411.     Prefix              *pp;        /* Prefix to find */
  412. {
  413.     struct sockaddr_in    sin;        /* INADDR_ANY for Rpc_Broadcast */
  414.     struct timeval      retry;        /* Retrans interval */
  415.     char                path[NFS_MAXPATHLEN];    /* Buffer for remote path */
  416.  
  417.     if (pp->serverName == NULL) {
  418.     /*
  419.      * Broadcast to locate the server for the thing, now
  420.      * we know the kernel really wants it...
  421.      */
  422.     if (!quiet) {
  423.         Message("Broadcasting for server of \"%s\"...", pp->path);
  424.     }
  425.     
  426.     /*
  427.      * Let Rpc_Broadcast figure the net(s) to which to go,
  428.      * but tell it what port to use...
  429.      */
  430.     sin.sin_family = AF_INET;
  431.     sin.sin_port = htons(PREFIX_PORT);
  432.     sin.sin_addr.s_addr = htonl(INADDR_ANY);
  433.     
  434.     /*
  435.      * Retry every second
  436.      */
  437.     retry.tv_sec = 1;
  438.     retry.tv_usec = 0;
  439.     
  440.     if (Rpc_Broadcast(prefixSock, &sin, PREFIX_LOCATE,
  441.               strlen(pp->path)+1, pp->path,
  442.               sizeof(path), path,
  443.               3, &retry,
  444.               ImportLocateResponse, (Rpc_Opaque)pp)!=RPC_SUCCESS)
  445.     {
  446.         /*
  447.          * No-one's got it -- return an error
  448.          */
  449.         if (!quiet) {
  450.         Message("no-one's home.");
  451.         }
  452.         return(0);
  453.     }
  454.     }
  455.     return(1);
  456. }
  457.  
  458.  
  459. /******************************************************************************
  460.  *
  461.  *               SUN-RPC SERVERS
  462.  *
  463.  *****************************************************************************/
  464.  
  465. /***********************************************************************
  466.  *                ImportNullReq
  467.  ***********************************************************************
  468.  * SYNOPSIS:        Let the caller know we're alive
  469.  * CALLED BY:        RFS_NULL
  470.  * RETURN:        SUNRPC_SUCCESS
  471.  * SIDE EFFECTS:    None
  472.  *
  473.  * STRATEGY:
  474.  *
  475.  * REVISION HISTORY:
  476.  *    Name    Date        Description
  477.  *    ----    ----        -----------
  478.  *    ardeb    9/10/89        Initial Revision
  479.  *
  480.  ***********************************************************************/
  481. static enum clnt_stat
  482. ImportNullReq(remote, msg, args, res, data, resPtr)
  483.     struct sockaddr_in    *remote;        /* Source of request */
  484.     Rpc_Message            msg;            /* Message token */
  485.     void            *args;            /* Arguments passed */
  486.     void            *res;            /* Results to return */
  487.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  488.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  489. {
  490.     return(SUNRPC_SUCCESS);
  491. }
  492.  
  493. /***********************************************************************
  494.  *                ImportGetAttrReq
  495.  ***********************************************************************
  496.  * SYNOPSIS:        Fetch the attributes of a prefix.
  497.  * CALLED BY:        SunRpc
  498.  * RETURN:        SUNRPC_SUCCESS (any error code is in result)
  499.  * SIDE EFFECTS:    None
  500.  *
  501.  * STRATEGY:
  502.  *
  503.  * REVISION HISTORY:
  504.  *    Name    Date        Description
  505.  *    ----    ----        -----------
  506.  *    ardeb    7/11/89        Initial Revision
  507.  *
  508.  ***********************************************************************/
  509. static enum clnt_stat
  510. ImportGetAttrReq(remote, msg, args, res, data, resPtr)
  511.     struct sockaddr_in    *remote;        /* Source of request */
  512.     Rpc_Message            msg;            /* Message token */
  513.     fhandle_t            *args;            /* Arguments passed */
  514.     struct nfsattrstat    *res;            /* Results to return */
  515.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  516.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  517. {
  518.     Prefix      *pp;        /* Prefix to stat */
  519.     char    path[512];  /* Path for filling in result */
  520.     
  521.     if (!IS_LOOKUP_HAN(args)) {
  522.     /*
  523.      * Really a prefix -- convert to a Prefix and return
  524.      * the stored attributes
  525.      */
  526.     pp = HandleToPrefix(args);
  527.         
  528.     if (pp == PREFIX_STALE) {
  529.         res->ns_status = NFSERR_STALE;
  530.     } else {
  531.         dprintf("GETATTR(%s)\n", pp->path);
  532.         
  533.         /*
  534.          * Install saved attributes
  535.          */
  536.         res->ns_status = NFS_OK;
  537.         res->ns_attr = pp->attr;
  538.     }
  539.     } else {
  540.     /*
  541.      * This is here only for safety. I doubt it will
  542.      * ever be called... WRONG! SunOS 4.0 calls this... I guess
  543.      * because we tell it to cache no attributes...
  544.      */
  545.     PrefixHandle        *lth = (PrefixHandle *)args;
  546.         
  547.     if (!IS_VALID_LH(args)) {
  548.         res->ns_status = NFSERR_STALE;
  549.     } else {
  550.         LookupToken    *ltp = lth->ld.ltp;
  551.         
  552.         dprintf("GETATTR(%s/%s)\n", ltp->prefix->path, ltp->name);
  553.         
  554.         /*
  555.          * Form path so we return the proper size
  556.          */
  557.         LT_PATH(path, ltp);
  558.         
  559.         /*
  560.          * Use default attributes for symbolic links.
  561.          */
  562.         res->ns_status = NFS_OK;
  563.  
  564.         ImportSetLinkAttr(&res->ns_attr, path, ltp->prefix);
  565.     }
  566.     }
  567.     return(SUNRPC_SUCCESS);
  568. }
  569.  
  570. /***********************************************************************
  571.  *                ImportReadLinkReq
  572.  ***********************************************************************
  573.  * SYNOPSIS:        Read the value of one of our "links"
  574.  * CALLED BY:        SunRpc
  575.  * RETURN:        SUNRPC_SUCCESS (link contents returned to caller)
  576.  * SIDE EFFECTS:    The server for the prefix is sought and the
  577.  *                serverName, server and remote fields for it filled in.
  578.  *
  579.  * STRATEGY:
  580.  *
  581.  * REVISION HISTORY:
  582.  *    Name    Date        Description
  583.  *    ----    ----        -----------
  584.  *    ardeb    7/11/89        Initial Revision
  585.  *
  586.  ***********************************************************************/
  587. static enum clnt_stat
  588. ImportReadLinkReq(remote, msg, args, res, data, resPtr)
  589.     struct sockaddr_in    *remote;        /* Source of request */
  590.     Rpc_Message            msg;            /* Message token */
  591.     fhandle_t            *args;            /* Arguments passed */
  592.     struct nfsrdlnres    *res;            /* Results to return */
  593.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  594.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  595. {
  596.     Prefix      *pp;
  597.     char        path[512];  /* Link's contents */
  598.     
  599.     /*
  600.      * Convert the handle into a token.
  601.      */
  602.     if (IS_LOOKUP_HAN(args)) {
  603.     if (!IS_VALID_LH(args)) {
  604.         /*
  605.          * Not in the active list -- must be stale
  606.          */
  607.         dprintf("READLINK -- stale handle\n");
  608.         res->rl_status = NFSERR_STALE;
  609.     } else {
  610.         LookupToken    *ltp;       /* Token we created during LOOKUP */
  611.     
  612.         ltp = ((PrefixHandle *)args)->ld.ltp;
  613.     
  614.         /*
  615.          * Make life easier by fetching out the prefix itself
  616.          */
  617.         pp = ltp->prefix;
  618.         
  619.         dprintf("READLINK(%s/%s)\n", pp->path, ltp->name);
  620.         
  621.         res->rl_status = NFS_OK;
  622.         
  623.         if (pp->serverName == NULL) {
  624.         /*
  625.          * We are not allowed to look for a prefix that is locked,
  626.          * as doing so could result in our deleting the thing while
  627.          * someone else is looking for it. The best way to handle
  628.          * this is to force the kernel to resubmit its request when
  629.          * we are more likely to be able to give it an answer. We
  630.          * do this by instructing SunRpc to drop the request on the
  631.          * floor.
  632.          */
  633.         if (PrefixIsLocked(pp)) {
  634.             return(SUNRPC_DONTRESPOND);
  635.         }
  636.         PrefixLock(pp);
  637.         if (!ImportLocatePrefix(pp)) {
  638.             /*
  639.              * If prefix is temporary and we were trying to locate
  640.              * it, we can safely delete the thing if we can't find
  641.              * its server. This will prevent repeated search for
  642.              * something due to "getwd" (which does a readdir and
  643.              * stat) when something gets into the prefix table
  644.              * unintentionally.
  645.              */
  646.             PrefixUnlock(pp);
  647.             if (pp->flags & PREFIX_TEMP) {
  648.             (void)ImportDeleteTemp(pp);
  649.             }
  650.             res->rl_status = NFSERR_NOENT;
  651.         } else {
  652.             PrefixUnlock(pp);
  653.         }
  654.         } else {
  655.         dprintf("served by %s[%s]\n", pp->serverName, pp->remote);
  656.         }
  657.         
  658.         if (res->rl_status == NFS_OK) {
  659.         /*
  660.          * Return a path to the "file" in the mount directory
  661.          * whose name is the ascii representation of the Prefix
  662.          * structure's address, with the component being sought
  663.          * just below that. The kernel should then perform a
  664.          * LOOKUP operation in the mount directory, at which
  665.          * time we should be able to unmount this thing and
  666.          * mount the real one. The kernel will track the
  667.          * extra component so we don't need to.
  668.          */
  669.         LT_PATH(path, ltp);
  670.         dprintf("returning \"%s\"\n", path);
  671.         /*
  672.          * Set up return value at the end of the nfsrdlnres
  673.          */
  674.         res->rl_count = strlen(path);
  675.         res = (struct nfsrdlnres *)realloc(res,
  676.                            sizeof(*res)+res->rl_count);
  677.         *resPtr = (void *)res;
  678.         res->rl_data = (char *)(res+1);
  679.         bcopy(path, res->rl_data, res->rl_count);
  680.         }
  681.     }
  682.     } else {
  683.     /*
  684.      * BOGUS -- should never happen
  685.      */
  686.     res->rl_status = NFSERR_STALE;
  687.     }
  688.     return(SUNRPC_SUCCESS);
  689. }
  690.  
  691. /***********************************************************************
  692.  *                ImportCreateTempPrefix
  693.  ***********************************************************************
  694.  * SYNOPSIS:        Create a new temporary prefix
  695.  * CALLED BY:        ImportLookupReq
  696.  * RETURN:        The Prefix * for the new prefix, linked into the
  697.  *                parent and the global list.
  698.  * SIDE EFFECTS:    All fields of the prefix are initialized.
  699.  *
  700.  * STRATEGY:
  701.  *
  702.  * REVISION HISTORY:
  703.  *    Name    Date        Description
  704.  *    ----    ----        -----------
  705.  *    ardeb    7/11/89        Initial Revision
  706.  *
  707.  ***********************************************************************/
  708. static Prefix *
  709. ImportCreateTempPrefix(path, pp)
  710.     char        *path;            /* Path for the prefix */
  711.     Prefix      *pp;            /* Parent prefix */
  712. {
  713.     Prefix          *newpp;
  714.     Prefix          *prev;
  715.     Prefix          *tp;
  716.     
  717.     newpp = AllocPrefix();
  718.     
  719.     newpp->path = (char *)malloc(strlen(path) + 1);
  720.     strcpy(newpp->path, path);
  721.     
  722.     /*
  723.      * Mark the prefix as temporary, so we don't remount the thing after
  724.      * deleting it.
  725.      */
  726.     newpp->flags = PREFIX_TEMP;
  727.     newpp->locks = 0;
  728.     
  729.     /*
  730.      * The new prefix is a clone of the root prefix, except for the file
  731.      * number...
  732.      */
  733.     newpp->options = pp->options;
  734.     newpp->attr = pp->attr;
  735.  
  736.     /* 
  737.      * Need to use a different file number to keep the kernel from getting
  738.      * confused.
  739.      */
  740.     if (pp->next) {
  741.     newpp->attr.na_nodeid = pp->next->attr.na_nodeid + 1;
  742.     } else {
  743.     newpp->attr.na_nodeid = pp->attr.na_nodeid + 1;
  744.     }
  745.     
  746.     /*
  747.      * Clear out the rest of the fields
  748.      */
  749.     newpp->unmount = (Rpc_Event)NULL;
  750.     newpp->serverName = newpp->remote = (char *)NULL;
  751.     
  752.     /*
  753.      * Record it.
  754.      */
  755.     (void)Lst_AtEnd(prefixes, (ClientData)newpp);
  756.     
  757.     /*
  758.      * Record it under its parent so we can deal with a READDIR on the parent
  759.      * (to allow for file completion, mostly). We place it at the end of
  760.      * the queue to try and avoid unnecessary mounts due to getwd() calls.
  761.      */
  762.     for (prev = pp, tp = pp->next; tp != NULL; prev = tp, tp = tp->next) {
  763.     ;
  764.     }
  765.     prev->next = newpp;
  766.     newpp->next = (Prefix *)NULL;
  767.  
  768.     return(newpp);
  769. }
  770.  
  771. /***********************************************************************
  772.  *                ImportLookupReq
  773.  ***********************************************************************
  774.  * SYNOPSIS:        Handle a LOOKUP operation in a prefix.
  775.  * CALLED BY:        SunRpc
  776.  * RETURN:        SUNRPC_SUCCESS (handle and attributes returned to caller)
  777.  * SIDE EFFECTS:    A LookupToken is created and saved
  778.  *
  779.  * STRATEGY:
  780.  *    The search of a prefix means its corresponding filesystem must
  781.  *    be mounted.
  782.  *
  783.  * REVISION HISTORY:
  784.  *    Name    Date        Description
  785.  *    ----    ----        -----------
  786.  *    ardeb    7/11/89        Initial Revision
  787.  *
  788.  ***********************************************************************/
  789. static enum clnt_stat
  790. ImportLookupReq(remote, msg, args, res, data, resPtr)
  791.     struct sockaddr_in    *remote;        /* Source of request */
  792.     Rpc_Message            msg;            /* Message token */
  793.     struct nfsdiropargs    *args;            /* Arguments passed */
  794.     struct nfsdiropres    *res;            /* Results to return */
  795.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  796.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  797. {
  798.     Prefix        *pp;        /* Prefix to import */
  799.     LookupToken        *ltp;       /* New token for later READLINK */
  800.     char        path[512];    /* Contents of "link" (for setting
  801.                  * size in link's attributes) */
  802.     
  803.     pp = HandleToPrefix(&args->da_fhandle);
  804.     
  805.     if (pp == PREFIX_STALE) {
  806.     res->dr_status = NFSERR_STALE;
  807.     } else {
  808.     dprintf("LOOKUP(%s:%s)\n", pp->path, args->da_name);
  809.     
  810.     if (args->da_name[0] == '.' &&
  811.         (args->da_name[1] == '\0' ||
  812.          (args->da_name[1] == '.' && args->da_name[2] == '\0')))
  813.     {
  814.         if (args->da_name[1] == '\0') {
  815.         /*
  816.          * Looking up itself -- return the stored attributes
  817.          * and the proper handle.
  818.          */
  819.         res->dr_status = NFS_OK;
  820.         res->dr_attr = pp->attr;
  821.         
  822.         PrefixToHandle(pp, &res->dr_fhandle);
  823.         } else if (pp->flags & PREFIX_TEMP) {
  824.         /*
  825.          * Want the parent of this sucker. Trim off the
  826.          * last component of the prefix call NameToPrefix
  827.          * to find it.
  828.          *
  829.          * This will only be invoked by the kernel if
  830.          * it encounters .. while in the root vnode of the
  831.          * temporary prefix, at which point it flips to
  832.          * the associated vnode in the root prefix's system
  833.          * to do the lookup, but the handle is still that
  834.          * of the temporary prefix...
  835.          */
  836.         char        *cp;    /* Start of final component */
  837.         Prefix        *ppp;   /* Parent Prefix Pointer */
  838.         
  839.         /*
  840.          * Just nuke the final slash...we'll put it back later.
  841.          */
  842.         cp = (char *)rindex(pp->path, '/');
  843.         *cp = '\0'; ppp = NameToPrefix(pp->path); *cp = '/';
  844.         
  845.         /*
  846.          * Set up the return value based on the parent.
  847.          */
  848.         res->dr_status = NFS_OK;
  849.         res->dr_attr = ppp->attr;
  850.         
  851.         PrefixToHandle(ppp, &res->dr_fhandle);
  852.         } else {
  853.         /*
  854.          * Why are you asking me this?
  855.          */
  856.         res->dr_status = NFSERR_NOENT;
  857.         }
  858.     } else if (pp->flags & PREFIX_ROOT) {
  859.         /*
  860.          * Special case -- looking something up in a ROOT
  861.          * prefix causes us to create a new temporary prefix,
  862.          * if one doesn't already exist.
  863.          */
  864.         Prefix  *newpp;     /* Prefix for component */
  865.         
  866.         /*
  867.          * Form full path for ease of comparison.
  868.          */
  869.         sprintf(path, "%s/%s", pp->path, args->da_name);
  870.         newpp = NameToPrefix(path);
  871.         
  872.         if (newpp == NULL) {
  873.         /*
  874.          * Doesn't exist yet -- create a new Prefix structure
  875.          * for the thing.
  876.          */
  877.         newpp = ImportCreateTempPrefix(path, pp);
  878.         }
  879.         
  880.         /*
  881.          * Set up to answer the query now, returning a
  882.          * standard handle for the prefix.
  883.          */
  884.         res->dr_status  = NFS_OK;
  885.         res->dr_attr    = newpp->attr;
  886.         PrefixToHandle(newpp, &res->dr_fhandle);
  887.     } else {
  888.         /*
  889.          * Create the LookupToken for the thing and put it on
  890.          * the end of the list of valid tokens.
  891.          */
  892.         struct timeval    deltok;    /* Interval for nuking */
  893.         
  894.         ltp = ImportAllocLookupToken();
  895.         
  896.         ltp->prefix     = pp;
  897.         ltp->name         = (char *)malloc(strlen(args->da_name)+1);
  898.         strcpy(ltp->name, args->da_name);
  899.         
  900.         (void)Lst_AtEnd(tokens, (ClientData)ltp);
  901.         
  902.         /*
  903.          * Register an event for deleting the lookup token
  904.          */
  905.         deltok.tv_sec = 10;
  906.         deltok.tv_usec = 0;
  907.         ltp->nukeEvent = Rpc_EventCreate(&deltok, ImportDeleteLookupToken,
  908.                          (Rpc_Opaque)ltp);
  909.         
  910.         /*
  911.          * Set up the return filehandle.
  912.          */
  913.         ImportTokenToHandle(ltp, &res->dr_fhandle);
  914.         
  915.         /*
  916.          * Set up the path so we can return an accurate size
  917.          */
  918.         LT_PATH(path, ltp);
  919.         
  920.         /*
  921.          * This is the same as for the GETATTR call... (not
  922.          * sure if the GETATTR support is necessary...)
  923.          */
  924.         res->dr_status  = NFS_OK;
  925.         ImportSetLinkAttr(&res->dr_attr, path, pp);
  926.     }
  927.     }
  928.     
  929.     return(SUNRPC_SUCCESS);
  930. }    
  931.  
  932.  
  933. /***********************************************************************
  934.  *                ImportStatFSReq
  935.  ***********************************************************************
  936.  * SYNOPSIS:        Handle a STATFS request
  937.  * CALLED BY:        SunRpc
  938.  * RETURN:        SUNRPC_SUCCESS (bogus statistics are returned to caller)
  939.  * SIDE EFFECTS:    None
  940.  *
  941.  * STRATEGY:
  942.  *    We don't know the actual parameters for a prefix since we don't
  943.  *    know who's serving the thing, nor are we going to find out
  944.  *    because of this call (which is issued whenever the prefix is
  945.  *    mounted), so we just return that the system is completely full.
  946.  *
  947.  * REVISION HISTORY:
  948.  *    Name    Date        Description
  949.  *    ----    ----        -----------
  950.  *    ardeb    7/11/89        Initial Revision
  951.  *
  952.  ***********************************************************************/
  953. static enum clnt_stat
  954. ImportStatFSReq(remote, msg, args, res, data, resPtr)
  955.     struct sockaddr_in    *remote;        /* Source of request */
  956.     Rpc_Message            msg;            /* Message token */
  957.     fhandle_t            *args;            /* Arguments passed */
  958.     struct nfsstatfs    *res;            /* Results to return */
  959.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  960.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  961. {
  962.     Prefix              *pp;
  963.     
  964.     pp = HandleToPrefix(args);
  965.     if (pp == PREFIX_STALE) {
  966.     res->fs_status = NFSERR_STALE;
  967.     } else {
  968.     dprintf("STATFS(%s)\n", pp->path);
  969.     
  970.     bzero(res, sizeof(*res));
  971.         
  972.     /*
  973.      * Return bogus information for the filesystem for now:
  974.      *  block and transfer size of 8192 bytes, 1 block in
  975.      *  the system and nothing is free...
  976.      */
  977.     res->fs_status = NFS_OK;
  978.     res->fs_tsize = res->fs_bsize = 8192;
  979.     res->fs_blocks = 1;
  980.     res->fs_bfree = 0;
  981.     res->fs_bavail = 0;
  982.         
  983.     }
  984.     return(SUNRPC_SUCCESS);
  985. }
  986.  
  987. /***********************************************************************
  988.  *                ImportReadDirReq
  989.  ***********************************************************************
  990.  * SYNOPSIS:        Handle a READDIR request on a prefix
  991.  * CALLED BY:        SunRpc
  992.  * RETURN:        SUNRPC_SUCCESS (directory entries are return to the caller)
  993.  * SIDE EFFECTS:    None
  994.  *
  995.  * STRATEGY:
  996.  *    For most prefixes, this just returns . and ..
  997.  *    For a root prefix, however, this returns the list of known
  998.  *    subprefixes.
  999.  *
  1000.  *    The offsets we return (via xdr_putdirres) do no correspond to
  1001.  *    file positions, as in a real NFS server. Instead, they are the
  1002.  *    prefix number (i.e. the position in the list).
  1003.  *
  1004.  * REVISION HISTORY:
  1005.  *    Name    Date        Description
  1006.  *    ----    ----        -----------
  1007.  *    ardeb    7/11/89        Initial Revision
  1008.  *
  1009.  ***********************************************************************/
  1010. static enum clnt_stat
  1011. ImportReadDirReq(remote, msg, args, res, data, resPtr)
  1012.     struct sockaddr_in    *remote;        /* Source of request */
  1013.     Rpc_Message            msg;            /* Message token */
  1014.     struct nfsrddirargs    *args;            /* Arguments passed */
  1015.     struct nfsrddirres    *res;            /* Results to return */
  1016.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  1017.     Rpc_Opaque        *resPtr;    /* Place holding address of "res". We
  1018.                      * need to enlarge the thing to hold
  1019.                      * the directory entries too... */
  1020. {
  1021.     Prefix              *pp;    /* Prefix being read */
  1022.     struct direct       *dirent;    /* All entries */
  1023.     
  1024.     /*
  1025.      * We do this very simply for now, storing all the
  1026.      * known entries into a buffer each time, then returning only
  1027.      * part of it. I always do brute-force, simplistic solutions
  1028.      * on the first pass. Besides, the other buffer will almost
  1029.      * always be big enough to hold it, I think, since we tell
  1030.      * the thing the FS has a block size of 8k...
  1031.      */
  1032.     dirent = NULL;
  1033.     
  1034.     pp = HandleToPrefix(&args->rda_fh);
  1035.     
  1036.     if (pp == PREFIX_STALE) {
  1037.     res->rd_status = NFSERR_STALE;
  1038.     } else {
  1039.     Prefix            *tp;    /* Current subprefix being
  1040.                  * counted or entered */
  1041.     int            i;    /* General counter */
  1042.     int             total;    /* Total number of entries */
  1043.     int            size;    /* General size quantity */
  1044.     struct direct   d;      /* For initial pass... */
  1045.     struct direct   *dp;    /* For subsequent passes... */
  1046.     
  1047.     dprintf("READDIR(%s): ", pp->path);
  1048.     
  1049.     /*
  1050.      * Count the number of entries available and figure the
  1051.      * size of buffer required to hold the entire list. We
  1052.      * need to use 'd' because the DIRSIZ macro only operates
  1053.      * on a struct direct (silly thing).
  1054.      *
  1055.      * Note this operation is only valid on a root prefix.
  1056.      * In particular, we have to avoid returning anything but
  1057.      * . and .. for a temporary prefix. If we don't, performing
  1058.      * 'ls -l' of a temporary prefix will cause us to try and
  1059.      * mount the prefix for each prefix after it at the same
  1060.      * level and each attempt will fail miserably because the
  1061.      * node is still locked.
  1062.      */
  1063.     total = size = 0;
  1064.     
  1065.     if (pp->flags & PREFIX_ROOT) {
  1066.         for (tp = pp->next; tp != NULL; tp=tp->next, total += 1) {
  1067.         char    *cp = (char *)rindex(tp->path, '/');
  1068.         
  1069.         d.d_namlen = strlen(cp+1);
  1070.         size += DIRSIZ(&d);
  1071.         }
  1072.     }
  1073.     
  1074.     /*
  1075.      * Add two for . and ..
  1076.      */
  1077.     d.d_namlen = 1;
  1078.     size += DIRSIZ(&d);
  1079.     
  1080.     d.d_namlen = 2;
  1081.     size += DIRSIZ(&d);
  1082.     
  1083.     total += 2;
  1084.     
  1085.     dprintf("%d entries requiring %d bytes\n", total, size);
  1086.     
  1087.     /*
  1088.      * Fill in the buffer now. The entries go immediately after the
  1089.      * result so the two can be freed at once by the rpc code.
  1090.      */
  1091.     res = (struct nfsrddirres *)realloc(res,
  1092.                         sizeof(struct nfsrddirres)+size);
  1093.     *resPtr = (Rpc_Opaque)res;
  1094.     dirent = (struct direct *)(res+1);
  1095.     
  1096.     dprintf("\tstoring:");
  1097.     /*
  1098.      * . comes first
  1099.      */
  1100.     dp = dirent;
  1101.     dp->d_fileno = pp->attr.na_nodeid;
  1102.     dp->d_namlen = 1;
  1103.     dp->d_name[0] = '.'; dp->d_name[1] = '\0';
  1104.     dp->d_reclen = DIRSIZ(dp);
  1105.     dp = (struct direct *)((char *)dp + dp->d_reclen);
  1106.     dprintf(" .");
  1107.     
  1108.     /*
  1109.      * .. next
  1110.      */
  1111.     dp->d_fileno = 3; /* BOGUS */
  1112.     dp->d_namlen = 2;
  1113.     dp->d_name[0] = '.'; dp->d_name[1] = '.';
  1114.     dp->d_name[2] = '\0';
  1115.     dp->d_reclen = DIRSIZ(dp);
  1116.     dp = (struct direct *)((char *)dp + dp->d_reclen);
  1117.     dprintf(" ..");
  1118.     
  1119.     /*
  1120.      * Now the rest of the entries
  1121.      */
  1122.     if (pp->flags & PREFIX_ROOT) {
  1123.         for (tp = pp->next; tp != NULL; tp = tp->next, i++){
  1124.         char        *cp = (char *)rindex(tp->path, '/');
  1125.         
  1126.         dp->d_fileno = tp->attr.na_nodeid;
  1127.         dp->d_namlen = strlen(cp+1);
  1128.         strcpy(dp->d_name, cp+1);
  1129.         dp->d_reclen = DIRSIZ(dp);
  1130.         dp = (struct direct *)((char *)dp + dp->d_reclen);
  1131.         dprintf(" %s", cp+1);
  1132.         }
  1133.     }
  1134.     
  1135.     dprintf("\n");
  1136.     /*
  1137.      * Find the start for the return value
  1138.      */
  1139.     
  1140.     dp = dirent;
  1141.     if (args->rda_offset < total) {
  1142.         dprintf("\tstarting at %d (skipping:", args->rda_offset);
  1143.         for (i = args->rda_offset; i > 0; i--) {
  1144.         dprintf(" %s", dp->d_name);
  1145.         dp = (struct direct *)((char *)dp + dp->d_reclen);
  1146.         }
  1147.         dprintf(")\n");
  1148.     } else {
  1149.         dprintf("\tread offset (%d) beyond range\n",
  1150.             args->rda_offset);
  1151.     }
  1152.     res->rd_entries = dp;
  1153.     
  1154.     /*
  1155.      * Skip over all those entries that will fit.
  1156.      * res->rd_offset starts out at the index of the first
  1157.      * entry being returned. xdr_putrddirres will up this
  1158.      * for each record encoded so it can deal with us
  1159.      * screwing up (not that we would, but better save than
  1160.      * sorry).
  1161.      */
  1162.     res->rd_offset = args->rda_offset;
  1163.     dprintf("\treturning:");
  1164.     for (size = args->rda_count, i = args->rda_offset;
  1165.          i < total;
  1166.          i++)
  1167.     {
  1168.         if ((size -= DIRSIZ(dp)) >= 0) {
  1169.         dprintf(" %s", dp->d_name);
  1170.         dp = (struct direct *)((char *)dp + dp->d_reclen);
  1171.         } else {
  1172.         break;
  1173.         }
  1174.     }
  1175.     
  1176.     /*
  1177.      * Set the final fields of the result, transferring
  1178.      * the buffer size from the args to the result for
  1179.      * xdr_putrddirres-> 
  1180.      */
  1181.     res->rd_bufsize = args->rda_count;
  1182.     res->rd_eof = (i == total);
  1183.     res->rd_size = (char *)dp - (char *)res->rd_entries;
  1184.     res->rd_status = NFS_OK;
  1185.     dprintf("\n\t%d bytes total, eof = %s, offset = %d\n",
  1186.         res->rd_size, res->rd_eof ? "true" : "false",
  1187.         res->rd_offset);
  1188.     }
  1189.     
  1190.     return(SUNRPC_SUCCESS);
  1191. }
  1192.         
  1193. /******************************************************************************
  1194.  *
  1195.  *              EXPORTED UTILITIES
  1196.  *
  1197.  *****************************************************************************/
  1198.  
  1199. /***********************************************************************
  1200.  *                Import_MountPrefix
  1201.  ***********************************************************************
  1202.  * SYNOPSIS:        Mount a prefix directory from ourselves. The prefix
  1203.  *            should have been checked for locks
  1204.  * CALLED BY:        ImportPrefix, ImportPrefixTree, MountUnmountPrefix
  1205.  * RETURN:        1 if successful
  1206.  * SIDE EFFECTS:    The Prefix is remounted
  1207.  *
  1208.  * STRATEGY:
  1209.  *
  1210.  * REVISION HISTORY:
  1211.  *    Name    Date        Description
  1212.  *    ----    ----        -----------
  1213.  *    ardeb    7/ 6/89        Initial Revision
  1214.  *
  1215.  ***********************************************************************/
  1216. int
  1217. Import_MountPrefix(pp)
  1218.     Prefix      *pp;        /* Prefix to remount */
  1219. {
  1220.     if (Lst_Member(prefixes, (ClientData)pp) == NILLNODE) {
  1221.     (void)Lst_AtEnd(prefixes, (ClientData)pp);
  1222.     }
  1223.     return (Child_Call(pp, PREFIX_MOUNT_LOCAL));
  1224. }
  1225.  
  1226. /***********************************************************************
  1227.  *                Import_CreatePrefix
  1228.  ***********************************************************************
  1229.  * SYNOPSIS:        Create a Prefix structure for a prefix
  1230.  * CALLED BY:        main, ImportPrefix, ImportPrefixTree
  1231.  * RETURN:        Nothing
  1232.  * SIDE EFFECTS:    The Prefix * is added to the prefixes list
  1233.  *
  1234.  * STRATEGY:
  1235.  *
  1236.  * REVISION HISTORY:
  1237.  *    Name    Date        Description
  1238.  *    ----    ----        -----------
  1239.  *    ardeb    7/ 7/89        Initial Revision
  1240.  *
  1241.  ***********************************************************************/
  1242. Prefix *
  1243. Import_CreatePrefix(path)
  1244.     char        *path;        /* Path of prefix (COPIED) */
  1245. {
  1246.     Prefix      *pp;        /* New prefix */
  1247.     struct stat    stb;        /* State of underlying directory, for conversion
  1248.                  * into prefix's stored attributes */
  1249.             
  1250.     if (path[0] != '/') {
  1251.     Message("prefix \"%s\" invalid -- must be absolute\n", path);
  1252.     return((Prefix *)NULL);
  1253.     }
  1254.     
  1255.     pp = AllocPrefix();
  1256.     pp->path = (char *)malloc(strlen(path) + 1);
  1257.     strcpy(pp->path, path);
  1258.             
  1259.     if (stat(pp->path, &stb) < 0) {
  1260.     perror(pp->path);
  1261.     free(pp->path);
  1262.     FreePrefix(pp);
  1263.     pp = (Prefix *)NULL;
  1264.     } else {
  1265.     /*
  1266.      * Convert the stat structure into an nfs attributes one. Prefixes
  1267.      * always appear to be read-only directories until they are mounted.
  1268.      * They take on the attributes of their underlying directory.
  1269.      */
  1270.     pp->attr.na_type            = NFDIR;
  1271.     pp->attr.na_mode             = 0555 | S_IFDIR;
  1272.     pp->attr.na_nlink            = 1;
  1273.     pp->attr.na_uid            = stb.st_uid;
  1274.     pp->attr.na_gid            = stb.st_gid;
  1275.     pp->attr.na_size        = stb.st_size;
  1276.     pp->attr.na_blocksize        = stb.st_blksize;
  1277.     pp->attr.na_rdev        = -1;
  1278.     pp->attr.na_blocks        = stb.st_blocks;
  1279.     pp->attr.na_fsid        = -1;
  1280.     pp->attr.na_nodeid        = stb.st_ino;
  1281.     pp->attr.na_atime.tv_sec    = stb.st_atime;
  1282.     pp->attr.na_atime.tv_usec   = stb.st_spare1;
  1283.     pp->attr.na_mtime.tv_sec    = stb.st_mtime;
  1284.     pp->attr.na_mtime.tv_usec   = stb.st_spare2;
  1285.     pp->attr.na_ctime.tv_sec    = stb.st_ctime;
  1286.     pp->attr.na_ctime.tv_usec   = stb.st_spare3;
  1287.  
  1288.     dprintf("importing %s\n", pp->path);
  1289.  
  1290.     pp->flags                   = 0;
  1291.     pp->locks            = 0;
  1292.     pp->unmount                 = (Rpc_Event)NULL;
  1293.     pp->next                    = (Prefix *)NULL;
  1294.     pp->serverName = pp->remote = (char *)NULL;
  1295.     pp->options                 = "rw";
  1296.  
  1297.     (void)Lst_AtEnd(prefixes, (ClientData)pp);
  1298.     }
  1299.  
  1300.     return(pp);
  1301. }
  1302.  
  1303. /***********************************************************************
  1304.  *                ImportDeleteTemp
  1305.  ***********************************************************************
  1306.  * SYNOPSIS:        Delete a temporary prefix.
  1307.  * CALLED BY:        ImportDelete, Rpc_Event (set up by Mount_Unmount)
  1308.  * RETURN:        0
  1309.  * SIDE EFFECTS:    The prefix is removed from the prefixes list and that
  1310.  *                of its parent root prefix.
  1311.  *
  1312.  * STRATEGY:
  1313.  *
  1314.  * REVISION HISTORY:
  1315.  *    Name    Date        Description
  1316.  *    ----    ----        -----------
  1317.  *    ardeb    9/10/89        Initial Revision
  1318.  *
  1319.  ***********************************************************************/
  1320. static int
  1321. ImportDeleteTemp(pp)
  1322.     Prefix      *pp;
  1323. {
  1324.     Prefix        **prev;     /* For traversal... */
  1325.     Prefix        *tp;
  1326.     char        *cp;
  1327.     LstNode         ln;
  1328.     
  1329.     if (PrefixIsLocked(pp)) {
  1330.     Message("Trying to delete temp prefix %s, but it's locked %d time%s",
  1331.         pp->path, pp->locks, pp->locks > 1 ? "s" : "");
  1332.     return(0);
  1333.     }
  1334.  
  1335.     /*
  1336.      * Strip off the final component of the doomed prefix's path and find
  1337.      * the corresponding prefix, which is its parent.
  1338.      */
  1339.     cp = (char *)rindex(pp->path, '/');
  1340.     /*
  1341.      * %%% ERROR CHECK %%%
  1342.      */
  1343.     if (cp == NULL) {
  1344.     Message("No / in temp prefix's path '%s'. What the f*** is going on?\n",
  1345.         pp->path);
  1346.     return(0);
  1347.     }
  1348.  
  1349.     *cp = '\0';
  1350.     tp = NameToPrefix(pp->path);
  1351.     
  1352.     /*
  1353.      * %%% ERROR CHECK %%%
  1354.      */
  1355.     if (tp == NULL) {
  1356.     *cp = '/';
  1357.     Message("Couldn't find root for temp prefix %s\n",
  1358.         pp->path);
  1359. #ifdef MEM_TRACE
  1360.     if (malloc_size(pp->path) > strlen(pp->path)+1) {
  1361.         cp = pp->path + strlen(pp->path);
  1362.         Message("\tremaining bytes in block = \"%.*s\"\n",
  1363.             (pp->path + malloc_size(pp->path))-cp, cp);
  1364.     }
  1365. #endif
  1366.     return (0);
  1367.     }
  1368.  
  1369.     /*
  1370.      * Invalidate any lookup tokens pending for this prefix.
  1371.      */
  1372.     for (ln = Lst_First(tokens); ln != NILLNODE;) {
  1373.     LookupToken *ltp = (LookupToken *)Lst_Datum(ln);
  1374.     
  1375.     ln = Lst_Succ(ln);
  1376.     
  1377.     if (ltp->prefix == pp) {
  1378.         ImportDeleteLookupToken(ltp, ltp->nukeEvent);
  1379.     }
  1380.     }
  1381.     
  1382.     /*
  1383.      * Find the prefix in the subprefix list for the root, keeping
  1384.      * track of the place where the pointer to the current node is
  1385.      * stored so the prefix can be removed once it's found.
  1386.      */
  1387.     for (prev = &tp->next, tp = tp->next; tp != pp; tp = *prev) {
  1388.     prev = &tp->next;
  1389.     }
  1390.     
  1391.     /*
  1392.      * Remove the prefix from the chain...
  1393.      */
  1394.     *prev = pp->next;
  1395.     
  1396.     /*
  1397.      * Free up the prefix's storage. Since it's not mounted, this
  1398.      * only involves the freeing of the path and the structure itself.
  1399.      */
  1400.     free(pp->path);
  1401.     FreePrefix(pp);
  1402.  
  1403.     return(0);
  1404. }
  1405. /******************************************************************************
  1406.  *
  1407.  *             CUSTOMS-RPC SERVERS
  1408.  *
  1409.  *****************************************************************************/
  1410.  
  1411.  
  1412. /***********************************************************************
  1413.  *                ImportCommon
  1414.  ***********************************************************************
  1415.  * SYNOPSIS:        Import a root or regular prefix
  1416.  * CALLED BY:        ImportPrefix, ImportPrefixRoot
  1417.  * RETURN:        Nothing
  1418.  * SIDE EFFECTS:    Another Prefix may be added to the list.
  1419.  *
  1420.  * STRATEGY:
  1421.  *
  1422.  * REVISION HISTORY:
  1423.  *    Name    Date        Description
  1424.  *    ----    ----        -----------
  1425.  *    ardeb    10/ 6/89        Initial Revision
  1426.  *
  1427.  ***********************************************************************/
  1428. static void
  1429. ImportCommon(msg, path, flags)
  1430.     Rpc_Message        msg;        /* Message for reply/error */
  1431.     char            *path;      /* Prefix to import */
  1432.     int                flags;      /* Initial flags for prefix */
  1433. {
  1434.     Prefix          *pp;        /* New prefix structure */
  1435.  
  1436.     /*
  1437.      * Make sure we're not duplicating an existing prefix. The only time
  1438.      * we allow this is when the user is converting a temporary prefix
  1439.      * to a permanent one (not sure why, but can't see any reason to disallow
  1440.      * it...)
  1441.      */
  1442.     pp = NameToPrefix(path);
  1443.     if (pp != NULL) {
  1444.     if (PrefixIsLocked(pp)) {
  1445.         Rpc_Error(msg, PREFIX_LOCKED);
  1446.     }
  1447.  
  1448.     PrefixLock(pp);
  1449.     if (pp->flags & PREFIX_TEMP) {
  1450.         /*
  1451.          * Converting a temporary prefix into a real one. If thing is
  1452.          * mounted remotely, we've nothing else to do -- when the
  1453.          * thing finally gets unmounted, it will be remounted on
  1454.          * us automatically. Otherwise, try and mount the thing on
  1455.          * ourselves.
  1456.          */
  1457.         pp->flags &= ~PREFIX_TEMP;
  1458.         pp->flags |= flags;
  1459.         if ((pp->flags & PREFIX_MOUNTED) || Import_MountPrefix(pp)) {
  1460.         Rpc_Return(msg, 0, NULL);
  1461.         } else {
  1462.         /*
  1463.          * Failure. I'm so ashamed. Make the prefix temporary again
  1464.          * and return a system error.
  1465.          */
  1466.         pp->flags |= PREFIX_TEMP;
  1467.         pp->flags &= ~flags;
  1468.         Rpc_Error(msg, RPC_SYSTEMERR);
  1469.         }
  1470.     } else {
  1471.         Rpc_Error(msg, DUPLICATE_PREFIX);
  1472.     }
  1473.     PrefixUnlock(pp);
  1474.     } else {
  1475.     pp = Import_CreatePrefix(path);
  1476.  
  1477.     if (pp == NULL) {
  1478.         Rpc_Error(msg, RPC_BADARGS);
  1479.     } else {
  1480.         /*
  1481.          * Set initial flags.
  1482.          */
  1483.         pp->flags = flags;
  1484.         
  1485.         /*
  1486.          * Mount the thing on ourselves
  1487.          */
  1488.         if (Import_MountPrefix(pp)) {
  1489.         /*
  1490.          * All ok -- return now.
  1491.          */
  1492.         Rpc_Return(msg, 0, NULL);
  1493.         } else {
  1494.         Rpc_Error(msg, RPC_SYSTEMERR);
  1495.         }
  1496.     }
  1497.     }
  1498. }
  1499.  
  1500. /***********************************************************************
  1501.  *                ImportPrefix
  1502.  ***********************************************************************
  1503.  * SYNOPSIS:        Import another prefix
  1504.  * CALLED BY:        PREFIX_IMPORT
  1505.  * RETURN:        Nothing
  1506.  * SIDE EFFECTS:    Another Prefix is added to the prefixes list
  1507.  *
  1508.  * STRATEGY:
  1509.  *
  1510.  * REVISION HISTORY:
  1511.  *    Name    Date        Description
  1512.  *    ----    ----        -----------
  1513.  *    ardeb    7/ 7/89        Initial Revision
  1514.  *
  1515.  ***********************************************************************/
  1516. static void
  1517. ImportPrefix(from, msg, len, data, serverData)
  1518.     struct sockaddr_in        *from;      /* Source of message */
  1519.     Rpc_Message                msg;        /* Mesage for reply/error */
  1520.     int                len;        /* Length of passed data (includes
  1521.                      * null byte at end of prefix) */
  1522.     Rpc_Opaque            data;       /* Name of prefix (null-terminated) */
  1523.     Rpc_Opaque                serverData;    /* Data we gave (UNUSED) */
  1524. {
  1525.     ImportCommon(msg, (char *)data, 0);
  1526. }
  1527.  
  1528.  
  1529. /***********************************************************************
  1530.  *                ImportPrefixRoot
  1531.  ***********************************************************************
  1532.  * SYNOPSIS:        Import a tree of prefixes
  1533.  * CALLED BY:        PREFIX_IMPORT_ROOT
  1534.  * RETURN:        Nothing
  1535.  * SIDE EFFECTS:    Another Prefix is added to the prefixes list
  1536.  *
  1537.  * STRATEGY:
  1538.  *
  1539.  * REVISION HISTORY:
  1540.  *    Name    Date        Description
  1541.  *    ----    ----        -----------
  1542.  *    ardeb    7/ 7/89        Initial Revision
  1543.  *
  1544.  ***********************************************************************/
  1545. static void
  1546. ImportPrefixRoot(from, msg, len, data, serverData)
  1547.     struct sockaddr_in        *from;      /* Source of message */
  1548.     Rpc_Message                msg;        /* Message for reply/error */
  1549.     int                len;        /* Length of passed data (includes
  1550.                      * null byte at end of prefix) */
  1551.     Rpc_Opaque            data;       /* Name of prefix (null-terminated) */
  1552.     Rpc_Opaque                serverData;    /* Data we gave (UNUSED) */
  1553. {
  1554.     ImportCommon(msg, (char *)data, PREFIX_ROOT);
  1555. }
  1556.  
  1557. /***********************************************************************
  1558.  *                ImportDelete
  1559.  ***********************************************************************
  1560.  * SYNOPSIS:        Delete a prefix.
  1561.  * CALLED BY:        PREFIX_DELETE
  1562.  * RETURN:        Nothing
  1563.  * SIDE EFFECTS:    If the prefix is a root prefix and it has mounted
  1564.  *                subprefixes, the subprefixes are deleted too.
  1565.  *
  1566.  * STRATEGY:
  1567.  *    - Locate prefix
  1568.  *    - If no such thing, pass the buck to the Export module
  1569.  *    - If we need to unmount the thing, fork and do so
  1570.  *    - Else if the prefix is temporary, delete it.
  1571.  *
  1572.  * REVISION HISTORY:
  1573.  *    Name    Date        Description
  1574.  *    ----    ----        -----------
  1575.  *    ardeb    7/ 8/89        Initial Revision
  1576.  *
  1577.  ***********************************************************************/
  1578. static void
  1579. ImportDelete(from, msg, len, data, serverData)
  1580.     struct sockaddr_in    *from;        /* Source of data */
  1581.     Rpc_Message        msg;        /* Message for reply/return */
  1582.     int            len;        /* Length of prefix (including null) */
  1583.     Rpc_Opaque        data;        /* Null-terminated prefix */
  1584.     Rpc_Opaque             serverData; /* Data we gave (UNUSED) */
  1585. {
  1586.     LstNode             ln;
  1587.     Prefix              *pp;
  1588.     char                *answer;
  1589.  
  1590.     pp = NameToPrefix((char *)data);
  1591.     
  1592.     if (pp == NULL) {
  1593.     /*
  1594.      * No such prefix -- complain.
  1595.      */
  1596.     answer = "no such prefix imported";
  1597.     goto ret;
  1598.     }
  1599.  
  1600.     if (PrefixIsLocked(pp)) {
  1601.     answer = "prefix is locked";
  1602.     goto ret;
  1603.     }
  1604.  
  1605.     answer = "Ok";
  1606.     /*
  1607.      * The case of an unmounted temporary prefix is special -- we need to
  1608.      * remove the thing not only from the prefixes list, but also from
  1609.      * its siblings in the subprefix list of its parent.
  1610.      *
  1611.      * For everything else, we need to unmount the thing from somewhere,
  1612.      * be it ourselves or its remote system.
  1613.      *
  1614.      * Note that the deletion of a mounted, temporary prefix is also special:
  1615.      * it takes two deletions to get rid of it.
  1616.      */
  1617.     if (((pp->flags & PREFIX_TEMP) == 0) || (pp->flags & PREFIX_MOUNTED))
  1618.     {
  1619.     if (pp->flags & PREFIX_ROOT) {
  1620.         /*
  1621.          * If the node's a root, attempt to unmount all its
  1622.          * subprefixes.
  1623.          */
  1624.         Prefix *tp;
  1625.  
  1626.         for (tp = pp->next; tp != NULL; tp = tp->next) {
  1627.         if ((tp->flags & PREFIX_MOUNTED) &&
  1628.             (!Mount_Unmount(tp, &answer)))
  1629.         {
  1630.             /*
  1631.              * Couldn't unmount subprefix, so can't unmount
  1632.              * top-level.
  1633.              */
  1634.             goto ret;
  1635.         }
  1636.         }
  1637.     }
  1638.  
  1639.     /*
  1640.      * Try and unmount the prefix itself.
  1641.      */
  1642.     if (pp->flags & PREFIX_MOUNTED) {
  1643.         if (!Mount_Unmount(pp, &answer)) {
  1644.         goto ret;
  1645.         }
  1646.     } else {
  1647.         /* 
  1648.          * Can't be temporary, so must have been mounted on ourselves.
  1649.          */
  1650.         if (!Child_Call(pp, PREFIX_UNMOUNT_LOCAL)) {
  1651.         answer = "Couldn't unmount from myself?";
  1652.         goto ret;
  1653.         }
  1654.     }
  1655.     if (!(pp->flags & PREFIX_TEMP)) {
  1656.         /*
  1657.          * Now nuke the Prefix descriptor(s) since everything's
  1658.          * disengaged, blowing away this prefix and all its
  1659.          * subprefixes. This works for non-roots too, since
  1660.          * prefixes have their 'next' field initialized to NULL.
  1661.          */
  1662.         while (pp != NULL) {
  1663.         Prefix    *next = pp->next;
  1664.         
  1665.         /*
  1666.          * Nuke any lookup tokens pending for the prefix.
  1667.          */
  1668.         for (ln = Lst_First(tokens); ln != NILLNODE; ) {
  1669.             LookupToken    *ltp = (LookupToken *)Lst_Datum(ln);
  1670.  
  1671.             ln = Lst_Succ(ln);
  1672.             if (ltp->prefix == pp) {
  1673.             ImportDeleteLookupToken(ltp, ltp->nukeEvent);
  1674.             }
  1675.         }
  1676.         
  1677.         free(pp->path);
  1678.         FreePrefix(pp);
  1679.         
  1680.         pp = next;
  1681.         }
  1682.     }
  1683.     } else if (pp->flags & PREFIX_TEMP) {
  1684.     (void)ImportDeleteTemp(pp);
  1685.     }
  1686.  
  1687. ret:
  1688.     Rpc_Return(msg, strlen(answer)+1, (Rpc_Opaque)answer);
  1689. }
  1690.  
  1691. /***********************************************************************
  1692.  *                ImportUnmount
  1693.  ***********************************************************************
  1694.  * SYNOPSIS:        Handle a PREFIX_UNMOUNT call from a server that's
  1695.  *                deleting an exported prefix.
  1696.  * CALLED BY:        PREFIX_UNMOUNT
  1697.  * RETURN:        An empty reply if couldn't unmount.
  1698.  * SIDE EFFECTS:    The serverName and remote fields are nulled and the
  1699.  *                remote system unmounted.
  1700.  *
  1701.  * STRATEGY:
  1702.  *    A lot like PREFIX_DELETE, except the prefix isn't deleted and
  1703.  *    a return value is only sent if there's an error.
  1704.  *
  1705.  * REVISION HISTORY:
  1706.  *    Name    Date        Description
  1707.  *    ----    ----        -----------
  1708.  *    ardeb    7/11/89        Initial Revision
  1709.  *
  1710.  ***********************************************************************/
  1711. static void
  1712. ImportUnmount(from, msg, len, data, serverData)
  1713.     struct sockaddr_in    *from;            /* Source of message */
  1714.     Rpc_Message            msg;            /* Message for reply/error */
  1715.     int                    len;            /* Length of parameters */
  1716.     Rpc_Opaque            data;            /* Parameters (prefix name) */
  1717.     Rpc_Opaque            serverData;    /* Data we gave (UNUSED) */
  1718. {
  1719.     if (ntohs(from->sin_port) != PREFIX_PORT) {
  1720.     Rpc_Error(msg, RPC_ACCESS);
  1721.     } else {
  1722.     LstNode        ln;
  1723.  
  1724.     for (ln = Lst_First(prefixes); ln != NILLNODE; ln = Lst_Succ(ln)) {
  1725.         Prefix  *pp;
  1726.  
  1727.         pp = (Prefix *)Lst_Datum(ln);
  1728.         
  1729.         if ((strcmp(pp->path, (char *)data) == 0) &&
  1730.         (pp->serverName != NULL) &&
  1731.         (pp->server.sin_addr.s_addr == from->sin_addr.s_addr))
  1732.         {
  1733.         char    *answer;    /* JUNK */
  1734.  
  1735.         if (PrefixIsLocked(pp)) {
  1736.             /*
  1737.              * If prefix in flux, we can't unmount it.
  1738.              */
  1739.             Rpc_Return(msg, 0, (Rpc_Opaque)NULL);
  1740.         } else if (pp->flags & PREFIX_MOUNTED) {
  1741.             if (!Mount_Unmount(pp, &answer)) {
  1742.             /*
  1743.              * Couldn't unmount -- let the server know
  1744.              */
  1745.             struct hostent    *he;
  1746.  
  1747.             Rpc_Return(msg, 0, (Rpc_Opaque)NULL);
  1748.  
  1749.             /*
  1750.              * Now tell people to stop using the thing.
  1751.              */
  1752.             he = gethostbyaddr(&from->sin_addr,
  1753.                        sizeof(from->sin_addr),
  1754.                        AF_INET);
  1755.             Message("Warning: %s trying to delete %s.",
  1756.                 he ? he->h_name : InetNtoA(from->sin_addr),
  1757.                 pp->path);
  1758.             Message("Please stop using its files");
  1759.             } else if (!(pp->flags & PREFIX_TEMP)) {
  1760.             /*
  1761.              * Remount on ourselves if not temporary.
  1762.              */
  1763.             Import_MountPrefix(pp);
  1764.             }
  1765.         } else {
  1766.             /*
  1767.              * Must have been "linked" to something else.
  1768.              * Just clear out the serverName and remote fields.
  1769.              */
  1770.             free(pp->serverName); free(pp->remote);
  1771.             pp->serverName = pp->remote = (char *)NULL;
  1772.         }
  1773.         break;
  1774.         }
  1775.     }
  1776.     }
  1777. }
  1778.     
  1779.     
  1780.  
  1781. /***********************************************************************
  1782.  *                Import_Init
  1783.  ***********************************************************************
  1784.  * SYNOPSIS:        Initialize this here module.
  1785.  * CALLED BY:        main
  1786.  * RETURN:        Nothing
  1787.  * SIDE EFFECTS:    The "tokens" list is created
  1788.  *
  1789.  * STRATEGY:
  1790.  *
  1791.  * REVISION HISTORY:
  1792.  *    Name    Date        Description
  1793.  *    ----    ----        -----------
  1794.  *    ardeb    7/ 6/89        Initial Revision
  1795.  *
  1796.  ***********************************************************************/
  1797. void
  1798. Import_Init()
  1799. {
  1800.     int                    addrlen;
  1801.     
  1802.     tokens = Lst_Init(FALSE);
  1803.     freeTokens = Lst_Init(FALSE);
  1804.  
  1805.     /*
  1806.      * Create the socket over which we will field the kernel's requests for
  1807.      * prefixes.
  1808.      */
  1809.     prefixSvc = Rpc_UdpCreate(True, 0);
  1810.     /*
  1811.      * Fetch the name of the socket so we can pass it to the kernel.
  1812.      * Actually, we don't really fetch the address. We just tell the kernel
  1813.      * to use its software loopback stuff. No point in routing the thing,
  1814.      * is there?
  1815.      */
  1816.     addrlen = sizeof(prefixMountAddr);
  1817.     if (getsockname(prefixSvc, &prefixMountAddr, &addrlen) < 0) {
  1818.     perror("getsockname:prefixSvc");
  1819.     exit(0);
  1820.     }
  1821.     prefixMountAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  1822.     prefixMountAddr.sin_family = AF_INET;
  1823.  
  1824.     /*
  1825.      * Register the Sun RPC servers for the socket. These are the only
  1826.      * NFS procedures we handle -- anything else generates a "procedure
  1827.      * unavailable" error.
  1828.      */
  1829.     SunRpc_ServerCreate(prefixSvc, NFS_PROGRAM, RFS_NULL, NFS_VERSION,
  1830.             ImportNullReq, (Rpc_Opaque)NULL,
  1831.             0, xdr_void, 0, xdr_void);
  1832.  
  1833.     SunRpc_ServerCreate(prefixSvc, NFS_PROGRAM, RFS_GETATTR, NFS_VERSION,
  1834.             ImportGetAttrReq, (Rpc_Opaque)NULL,
  1835.             sizeof(fhandle_t), xdr_fhandle,
  1836.             sizeof(struct nfsattrstat), xdr_attrstat);
  1837.  
  1838.     SunRpc_ServerCreate(prefixSvc, NFS_PROGRAM, RFS_READLINK, NFS_VERSION,
  1839.             ImportReadLinkReq, (Rpc_Opaque)NULL,
  1840.             sizeof(fhandle_t), xdr_fhandle,
  1841.             sizeof(struct nfsrdlnres), xdr_rdlnres);
  1842.  
  1843.     SunRpc_ServerCreate(prefixSvc, NFS_PROGRAM, RFS_LOOKUP, NFS_VERSION,
  1844.             ImportLookupReq, (Rpc_Opaque)NULL,
  1845.             sizeof(struct nfsdiropargs), xdr_diropargs,
  1846.             sizeof(struct nfsdiropres), xdr_diropres);
  1847.  
  1848.     SunRpc_ServerCreate(prefixSvc, NFS_PROGRAM, RFS_STATFS, NFS_VERSION,
  1849.             ImportStatFSReq, (Rpc_Opaque)NULL,
  1850.             sizeof(fhandle_t), xdr_fhandle,
  1851.             sizeof(struct nfsstatfs), xdr_statfs);
  1852.  
  1853.     SunRpc_ServerCreate(prefixSvc, NFS_PROGRAM, RFS_READDIR, NFS_VERSION,
  1854.             ImportReadDirReq, (Rpc_Opaque)NULL,
  1855.             sizeof(struct nfsrddirargs), xdr_rddirargs,
  1856.             sizeof (struct nfsrddirres), xdr_putrddirres);
  1857.  
  1858.     Rpc_ServerCreate(prefixSock, PREFIX_IMPORT, ImportPrefix, NULL, NULL,
  1859.              NULL);
  1860.     Rpc_ServerCreate(prefixSock, PREFIX_IMPORT_ROOT, ImportPrefixRoot,
  1861.              NULL, NULL, NULL);
  1862.     Rpc_ServerCreate(prefixSock, PREFIX_DELETE, ImportDelete, NULL, NULL,
  1863.              NULL);
  1864.     Rpc_ServerCreate(prefixSock, PREFIX_UNMOUNT, ImportUnmount, NULL, NULL,
  1865.              NULL);
  1866.  
  1867. }
  1868.